﻿#include "threadsafe.h"
#include "eventloop.h"

ThreadSafe::Event::Event(int type)
{
	this->type = type;
}

ThreadSafe::Event::~Event()
{
}

ThreadSafe::DeleteEvent::DeleteEvent():Event(Event::Delete)
{
}

ThreadSafe::ThreadSafeBase::ThreadSafeBase()
{
	auto p = new ThreadSafeBase*(this);
	selfPointer.reset(p);

	EventLoop::Register(this);
}

ThreadSafe::ThreadSafeBase::~ThreadSafeBase()
{
	EventLoop::UnRegister(this);
	Destoried();
}

ThreadSafe::ThreadId ThreadSafe::ThreadSafeBase::thread()
{
	return EventLoop::GetThread(this);
}

void ThreadSafe::ThreadSafeBase::MoveToThread(ThreadId id)
{
	EventLoop::MoveThread(this, id);
}

void ThreadSafe::ThreadSafeBase::HandleEvent(Event * event)
{
	switch (event->GetType())
	{
	case Event::Delete:
		DeleteEvent(static_cast<ThreadSafe::DeleteEvent*>(event));
		break;

	case Event::InvokeFunction:
		InvokeFunctionEvent(static_cast<ThreadSafe::InvokeFunctionEvent*>(event));
		break;
	default:
		break;
	}
}

void ThreadSafe::ThreadSafeBase::DeleteEvent(ThreadSafe::DeleteEvent*)
{
	delete this;
}

void ThreadSafe::ThreadSafeBase::InvokeFunctionEvent(ThreadSafe::InvokeFunctionEvent * event)
{
	event->Invoke();
}

bool ThreadSafe::ThreadSafeBase::FilterEvent(ThreadSafeBase * obj, Event * event)
{
	return false;
}

bool ThreadSafe::ThreadSafeBase::FilterEvent(Event * event)
{
	return false;
}

void ThreadSafe::ThreadSafeBase::DeleteLater()
{
	EventLoop::PostEvent(this, new ThreadSafe::DeleteEvent());
}

ConnectionRegistry * ThreadSafe::ThreadSafeBase::GetRegistry()
{
	return &m_Registry;
}

void ThreadSafe::ThreadSafeBase::InstallEventFilter(ThreadSafeBase * filter)
{
}

void ThreadSafe::ThreadSafeBase::UninstallEventFilter(ThreadSafeBase * filter)
{
}

ThreadSafe::InvokeFunctionEvent::InvokeFunctionEvent(const std::function<void()>& fun):Event(Event::InvokeFunction)
{
	this->fun = fun;
}

void ThreadSafe::InvokeFunctionEvent::Invoke()
{
	if (fun) {
		fun();
	}
}

ThreadSafe::TimerEvent::TimerEvent() :Event(Event::Timer)
{

}

ThreadSafe::ObjectRegistryBase::ObjectRegistryBase()
{

}

ThreadSafe::ObjectRegistryBase::~ObjectRegistryBase()
{
}

void ThreadSafe::ObjectRegistryBase::Register(ThreadSafeBase * o)
{
	std::lock_guard<std::mutex> lock(mutex);
	if (o && !objs.count(o)) {
		auto con = o->Destoried.Bind([=]() {
			UnRegister(o);
		});
		objs[o] = con;
	}
}

void ThreadSafe::ObjectRegistryBase::UnRegister(ThreadSafeBase * o)
{
	std::lock_guard<std::mutex> lock(mutex);
	if (objs.count(o)) {
		GenericSignal::UnBind(objs[o]);
		objs.erase(o);
	}
}

std::unordered_set<ThreadSafe::ThreadSafeBase*> ThreadSafe::ObjectRegistryBase::GetContent() const
{
	std::lock_guard<std::mutex> lock(mutex);
	std::unordered_set<ThreadSafe::ThreadSafeBase*> ret;
	for (auto&i : objs) {
		ret.insert(i.first);
	}

	return ret;
}
